/*
 * File      : bb_except.h
 * This file is part of Black Bird Simulation Platform
 * Copyright 2013-2020 BB(Black Bird) Development Team.  
 * All rights reserved.
 *
 * Change Logs:
 * Date           Author       Notes
 * 2013-10-27    Holt         First Version
 */
#ifndef __BB_EXCEPT_INCLUDE__
#define __BB_EXCEPT_INCLUDE__
#include <setjmp.h>
#include "bb_type.h"
enum 
{
	EXCEPTION_ENTERED	= 0,
	EXCEPTION_RAISED,
	EXCEPTION_HANDLED,
	EXCEPTION_FINALIZED
};

struct bb_except
{
	char *reason;
};
typedef struct bb_expect* bb_except_t;

struct bb_except_frame
{
	struct bb_except_frame* prev;
	jmp_buf	env;
	const char * file;
	bb_base line;
	bb_except_t exception;
};
typedef struct bb_except_frame* bb_except_frame_t;

extern bb_except_frame_t except_stack;
void bb_except_raise(const bb_except_t e, const char *file,bb_base line);

#define BB_RAISE(e) bb_except_raise((e), __FILE__, __LINE__)
#define BB_RERAISE  bb_except_raise(except_this.exception, \
	except_this.file, except_this.line)
	
#define TRY do { \
	volatile bb_base except_flag; \
	struct bb_except except_this; \
	except_this.prev = except_stack; \
	except_stack = &except_this;  \
	except_flag = setjmp(except_this.env); \
	if (except_flag == EXCEPTION_ENTERED) \
	{
	
#define EXCEPT(e) \
		if (except_flag == EXCEPTION_ENTERED) \
			except_stack = except_stack->prev; \
	}\
	else if (except_this.exception == &(e))\
	{\
		except_flag = EXCEPTION_HANDLED;\
		
#define ELSE \
		if (except_flag == EXCEPTION_ENTERED) \
			except_stack = except_stack->prev; \
	}\
	else \
	{	 \
		except_flag = EXCEPTION_HANDLED;
		
#define FINALLY \
		if (except_flag == EXCEPTION_ENTERED) \
			except_stack = except_stack->prev; \
	}\
	if (except_flag == EXCEPTION_ENTERED) \
		except_flag = EXCEPTION_FINALIZED;
		
#define END_TRY \
	if (except_flag == EXCEPTION_RAISED) \
		RERAISE; \
} while (0)
#endif